home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / hardware / adflib / adflibppc / lib / adf_dir.c < prev    next >
C/C++ Source or Header  |  1999-06-14  |  24KB  |  969 lines

  1. /*
  2.  *  ADF Library. (C) 1997-1998 Laurent Clevy
  3.  *
  4.  *  adf_dir.c
  5.  *
  6.  *  directory code
  7.  */
  8.  
  9. #include<stdlib.h>
  10. #include<string.h>
  11. #include<ctype.h>
  12.  
  13. #include"adf_dir.h"
  14. #include"adf_str.h"
  15. #include"adf_util.h"
  16. #include"defendian.h"
  17. #include"adf_blk.h"
  18. #include"adf_raw.h"
  19. #include"adf_disk.h"
  20. #include"adf_bitm.h"
  21. #include"adf_file.h"
  22. #include"adf_err.h"
  23. #include"adf_cache.h"
  24.  
  25. extern struct Env adfEnv;
  26.  
  27.  
  28. /*
  29.  * adfRenameEntry
  30.  *
  31.  */ 
  32. RETCODE adfRenameEntry(struct Volume *vol, SECTNUM pSect, char *oldName,
  33.     SECTNUM nPSect, char *newName)
  34. {
  35.     struct bEntryBlock parent, previous, entry, nParent;
  36.     SECTNUM nSect2, nSect, prevSect, tmpSect;
  37.     int hashValueO, hashValueN, len;
  38.     char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1];
  39.     BOOL intl;
  40.     RETCODE rc;
  41.  
  42.     if (strcmp(oldName,newName)==0)
  43.         return RC_OK;
  44.     
  45.     intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
  46.     len = strlen(newName);
  47.     myToUpper(name2, newName, len, intl);
  48.     myToUpper(name3, oldName, strlen(oldName), intl);
  49.     /* newName == oldName ? */
  50.  
  51.     if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK)
  52.         return RC_ERROR;
  53.  
  54.     hashValueO = adfGetHashValue(oldName, intl);
  55.  
  56.     nSect = adfNameToEntryBlk(vol, parent.hashTable, oldName, &entry, &prevSect);
  57.     if (nSect==-1) {
  58.         (*adfEnv.wFct)("adfRenameEntry : existing entry not found");
  59.         return RC_ERROR;
  60.     }
  61.  
  62.     /* change name and parent dir */
  63.     entry.nameLen = min(31, strlen(newName));
  64.     memcpy(entry.name, newName, entry.nameLen);
  65.     entry.parent = nPSect;
  66.     tmpSect = entry.nextSameHash;
  67.  
  68.     entry.nextSameHash = 0;
  69.     if (adfWriteEntryBlock(vol, nSect, &entry)!=RC_OK)
  70.         return RC_ERROR;
  71.  
  72.     /* del from the oldname list */
  73.  
  74.     /* in hashTable */
  75.     if (prevSect==0) {
  76.         parent.hashTable[hashValueO] = tmpSect;
  77.         if (parent.secType==ST_ROOT)
  78.             rc = adfWriteRootBlock(vol, pSect, (struct bRootBlock*)&parent);
  79.         else
  80.             rc = adfWriteDirBlock(vol, pSect, (struct bDirBlock*)&parent);
  81.         if (rc!=RC_OK)
  82.             return rc;
  83.     }
  84.     else {
  85.         /* in linked list */
  86.         if (adfReadEntryBlock(vol, prevSect, &previous)!=RC_OK)
  87.             return RC_ERROR;
  88.         /* entry.nextSameHash (tmpSect) could be == 0 */
  89.         previous.nextSameHash = tmpSect;
  90.         if (adfWriteEntryBlock(vol, prevSect, &previous)!=RC_OK)
  91.             return RC_ERROR;
  92.     }
  93.  
  94.  
  95.     if (adfReadEntryBlock( vol, nPSect, &nParent )!=RC_OK)
  96.         return RC_ERROR;
  97.  
  98.     hashValueN = adfGetHashValue(newName, intl);
  99.     nSect2 = nParent.hashTable[ hashValueN ];
  100.     /* no list */
  101.     if (nSect2==0) {
  102.         nParent.hashTable[ hashValueN ] = nSect;
  103.         if (nParent.secType==ST_ROOT)
  104.             rc = adfWriteRootBlock(vol, nPSect, (struct bRootBlock*)&nParent);
  105.         else
  106.             rc = adfWriteDirBlock(vol, nPSect, (struct bDirBlock*)&nParent);
  107.     }
  108.     else {
  109.         /* a list exists : addition at the end */
  110.         /* len = strlen(newName);
  111.                    * name2 == newName
  112.                    */
  113.         do {
  114.             if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK)
  115.                 return -1;
  116.             if (previous.nameLen==len) {
  117.                 myToUpper(name3,previous.name,previous.nameLen,intl);
  118.                 if (strncmp(name3,name2,len)==0) {
  119.                     (*adfEnv.wFct)("adfRenameEntry : entry already exists");
  120.                     return -1;
  121.                 }
  122.             }
  123.             nSect2 = previous.nextSameHash;
  124. //printf("sect=%ld\n",nSect2);
  125.         }while(nSect2!=0);
  126.         
  127.         previous.nextSameHash = nSect;
  128.         if (previous.secType==ST_DIR)
  129.             rc=adfWriteDirBlock(vol, previous.headerKey, 
  130.                    (struct bDirBlock*)&previous);
  131.         else if (previous.secType==ST_FILE)
  132.             rc=adfWriteFileHdrBlock(vol, previous.headerKey, 
  133.                    (struct bFileHeaderBlock*)&previous);
  134.         else {
  135.             (*adfEnv.wFct)("adfRenameEntry : unknown entry type");
  136.             rc = RC_ERROR;
  137.         }
  138.     
  139.     }
  140.     if (rc!=RC_OK)
  141.         return rc;
  142.  
  143.     if (isDIRCACHE(vol->dosType))
  144.         if (pSect==nPSect) {
  145.             adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry,TRUE);
  146.         }
  147.         else {
  148.             adfDelFromCache(vol,&parent,entry.headerKey);
  149.             adfAddInCache(vol,&nParent,&entry);
  150.         }
  151. /*
  152.     if (isDIRCACHE(vol->dosType) && pSect!=nPSect) {
  153.         adfUpdateCache(vol, &nParent, (struct bEntryBlock*)&entry,TRUE);
  154.     }
  155. */
  156.     return RC_OK;
  157. }
  158.  
  159. /*
  160.  * adfRemoveEntry
  161.  *
  162.  */
  163. RETCODE adfRemoveEntry(struct Volume *vol, SECTNUM pSect, char *name)
  164. {
  165.     struct bEntryBlock parent, previous, entry;
  166.     SECTNUM nSect2, nSect;
  167.     int hashVal;
  168.     BOOL intl;
  169.  
  170.     if (adfReadEntryBlock( vol, pSect, &parent )!=RC_OK)
  171.         return RC_ERROR;
  172.     nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, &nSect2);
  173.     if (nSect==-1) {
  174.         (*adfEnv.wFct)("adfRemoveEntry : entry not found");
  175.         return RC_ERROR;
  176.     }
  177.     /* if it is a directory, is it empty ? */
  178.     if ( entry.secType==ST_DIR && !isDirEmpty((struct bDirBlock*)&entry) ) {
  179.         (*adfEnv.wFct)("adfRemoveEntry : directory not empty");
  180.         return RC_ERROR;
  181.     }
  182. /*    printf("name=%s  nSect2=%ld\n",name, nSect2);*/
  183.  
  184.     /* in parent hashTable */
  185.     if (nSect2==0) {
  186.         intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
  187.         hashVal = adfGetHashValue( name, intl );
  188. /*printf("hashTable=%d nexthash=%d\n",parent.hashTable[hashVal],
  189.  entry.nextSameHash);*/
  190.         parent.hashTable[hashVal] = entry.nextSameHash;
  191.         if (adfWriteEntryBlock(vol, pSect, &parent)!=RC_OK)
  192.             return RC_ERROR;
  193.     }
  194.     /* in linked list */
  195.     else {
  196.         if (adfReadEntryBlock(vol, nSect2, &previous)!=RC_OK)
  197.             return RC_ERROR;
  198.         previous.nextSameHash = entry.nextSameHash;
  199.         if (adfWriteEntryBlock(vol, nSect2, &previous)!=RC_OK)
  200.             return RC_ERROR;
  201.     }
  202.  
  203.     if (entry.secType==ST_FILE) {
  204.         adfFreeFileBlocks(vol, (struct bFileHeaderBlock*)&entry);
  205.         (*adfEnv.notifyFct)(pSect,ST_FILE);
  206.     }
  207.     else {
  208.         adfSetBlockFree(vol, nSect);
  209.         (*adfEnv.notifyFct)(pSect,ST_DIR);
  210.     }
  211.  
  212.     if (isDIRCACHE(vol->dosType))
  213.         adfDelFromCache(vol, &parent, entry.headerKey);
  214.  
  215.     adfUpdateBitmap(vol);
  216.  
  217.     return RC_OK;
  218. }
  219.  
  220.  
  221. /*
  222.  * adfSetEntryComment
  223.  *
  224.  */
  225. RETCODE adfSetEntryComment(struct Volume* vol, SECTNUM parSect, char* name,
  226.     char* newCmt)
  227. {
  228.     struct bEntryBlock parent, entry;
  229.     SECTNUM nSect;
  230.  
  231.     if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK)
  232.         return RC_ERROR;
  233.     nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL);
  234.     if (nSect==-1) {
  235.         (*adfEnv.wFct)("adfSetEntryComment : entry not found");
  236.         return RC_ERROR;
  237.     }
  238.  
  239.     entry.commLen = min(MAXCMMTLEN, strlen(newCmt));
  240.     memcpy(entry.comment, newCmt, entry.commLen);
  241.  
  242.     if (entry.secType==ST_DIR)
  243.         adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry);
  244.     else if (entry.secType==ST_FILE)
  245.         adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry);
  246.     else
  247.         (*adfEnv.wFct)("adfSetEntryComment : entry secType incorrect");
  248.  
  249.     if (isDIRCACHE(vol->dosType))
  250.         adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, TRUE);
  251.  
  252.     return RC_OK;
  253. }
  254.  
  255.  
  256. /*
  257.  * adfSetEntryAccess
  258.  *
  259.  */
  260. RETCODE adfSetEntryAccess(struct Volume* vol, SECTNUM parSect, char* name,
  261.     long newAcc)
  262. {
  263.     struct bEntryBlock parent, entry;
  264.     SECTNUM nSect;
  265.  
  266.     if (adfReadEntryBlock( vol, parSect, &parent )!=RC_OK)
  267.         return RC_ERROR;
  268.     nSect = adfNameToEntryBlk(vol, parent.hashTable, name, &entry, NULL);
  269.     if (nSect==-1) {
  270.         (*adfEnv.wFct)("adfSetEntryAccess : entry not found");
  271.         return RC_ERROR;
  272.     }
  273.  
  274.     entry.access = newAcc;
  275.     if (entry.secType==ST_DIR)
  276.         adfWriteDirBlock(vol, nSect, (struct bDirBlock*)&entry);
  277.     else if (entry.secType==ST_FILE)
  278.         adfWriteFileHdrBlock(vol, nSect, (struct bFileHeaderBlock*)&entry);
  279.     else
  280.         (*adfEnv.wFct)("adfSetEntryAccess : entry secType incorrect");
  281.  
  282.     if (isDIRCACHE(vol->dosType))
  283.         adfUpdateCache(vol, &parent, (struct bEntryBlock*)&entry, FALSE);
  284.  
  285.     return RC_OK;
  286. }
  287.  
  288.  
  289. /*
  290.  * isDirEmpty
  291.  *
  292.  */
  293. BOOL isDirEmpty(struct bDirBlock *dir)
  294. {
  295.     int i;
  296.     
  297.     for(i=0; i<HT_SIZE; i++)
  298.         if (dir->hashTable[i]!=0)
  299.            return FALSE;
  300.  
  301.     return TRUE;
  302. }
  303.  
  304.  
  305. /*
  306.  * adfFreeDirList
  307.  *
  308.  */
  309. void adfFreeDirList(struct List* list)
  310. {
  311.     struct List *root, *cell;
  312.  
  313.     root = cell = list;
  314.     while(cell!=NULL) {
  315.         adfFreeEntry(cell->content);
  316.         if (cell->subdir!=NULL)
  317.             adfFreeDirList(cell->subdir);
  318.         cell = cell->next;
  319.     }
  320.     freeList(root);
  321. }
  322.  
  323.  
  324. /*
  325.  * adfGetRDirEnt
  326.  *
  327.  */
  328. struct List* adfGetRDirEnt(struct Volume* vol, SECTNUM nSect, BOOL recurs )
  329. {
  330.     struct bEntryBlock entryBlk;
  331.     struct List *cell, *head;
  332.     int i;
  333.     struct Entry *entry;
  334.     SECTNUM nextSector;
  335.     long *hashTable;
  336.     struct bEntryBlock parent;
  337.  
  338.  
  339.     if (adfEnv.useDirCache && isDIRCACHE(vol->dosType))
  340.         return (adfGetDirEntCache(vol, nSect, recurs ));
  341.  
  342.  
  343.     if (adfReadEntryBlock(vol,nSect,&parent)!=RC_OK)
  344.         return NULL;
  345.  
  346.     hashTable = parent.hashTable;
  347.     cell = head = NULL;
  348.     for(i=0; i<HT_SIZE; i++) {
  349.         if (hashTable[i]!=0) {
  350.              entry = (struct Entry *)malloc(sizeof(struct Entry));
  351.              if (!entry) {
  352.                  adfFreeDirList(head);
  353.                  (*adfEnv.eFct)("adfGetDirEnt : malloc");
  354.                  return NULL;
  355.              }
  356.              if (adfReadEntryBlock(vol, hashTable[i], &entryBlk)!=RC_OK) {
  357.                  adfFreeDirList(head);
  358.                  return NULL;
  359.              }
  360.              if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
  361.                  adfFreeDirList(head); return NULL;
  362.              }
  363.              entry->sector = hashTable[i];
  364.     
  365.              if (head==NULL)
  366.                  head = cell = newCell(0, (void*)entry);
  367.              else
  368.                  cell = newCell(cell, (void*)entry);
  369.              if (cell==NULL) {
  370.                  adfFreeDirList(head); return NULL;
  371.              }
  372.  
  373.              if (recurs && entry->type==ST_DIR)
  374.                  cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);
  375.  
  376.              /* same hashcode linked list */
  377.              nextSector = entryBlk.nextSameHash;
  378.              while( nextSector!=0 ) {
  379.                  entry = (struct Entry *)malloc(sizeof(struct Entry));
  380.                  if (!entry) {
  381.                      adfFreeDirList(head);
  382.                      (*adfEnv.eFct)("adfGetDirEnt : malloc");
  383.                      return NULL;
  384.                  }
  385.                  if (adfReadEntryBlock(vol, nextSector, &entryBlk)!=RC_OK) {
  386.                      adfFreeDirList(head); return NULL;
  387.                  }
  388.  
  389.                  if (adfEntBlock2Entry(&entryBlk, entry)!=RC_OK) {
  390.                      adfFreeDirList(head);
  391.                      return NULL;
  392.                  }
  393.                  entry->sector = nextSector;
  394.     
  395.                  cell = newCell(cell, (void*)entry);
  396.                  if (cell==NULL) {
  397.                      adfFreeDirList(head); return NULL;
  398.                  }
  399.                  
  400.                  if (recurs && entry->type==ST_DIR)
  401.                      cell->subdir = adfGetRDirEnt(vol,entry->sector,recurs);
  402.                  
  403.                  nextSector = entryBlk.nextSameHash;
  404.              }
  405.         }
  406.     }
  407.  
  408. /*    if (parent.extension && isDIRCACHE(vol->dosType) )
  409.         adfReadDirCache(vol,parent.extension);
  410. */
  411.     return head;
  412. }
  413.  
  414.  
  415. /*
  416.  * adfGetDirEnt
  417.  *
  418.  */
  419. struct List* adfGetDirEnt(struct Volume* vol, SECTNUM nSect )
  420. {
  421.     return adfGetRDirEnt(vol, nSect, FALSE);
  422. }
  423.  
  424.  
  425. /*
  426.  * adfFreeEntry
  427.  *
  428.  */
  429. void adfFreeEntry(struct Entry *entry)
  430. {
  431.     if (entry==NULL)
  432.        return;
  433.     if (entry->name)
  434.         free(entry->name);
  435.     if (entry->comment)
  436.         free(entry->comment);
  437.     free(entry);    
  438. }
  439.  
  440.  
  441. /*
  442.  * adfChangeDir
  443.  *
  444.  */
  445. RETCODE adfChangeDir(struct Volume* vol, char *name)
  446. {
  447.     struct bEntryBlock entry;
  448.     SECTNUM nSect;
  449.  
  450.     if (adfReadEntryBlock( vol, vol->curDirPtr, &entry )!=RC_OK)
  451.         return RC_ERROR;
  452.     nSect = adfNameToEntryBlk(vol, entry.hashTable, name, &entry, NULL);
  453. /*printf("adfChangeDir=%d\n",nSect);*/
  454.     if (nSect!=-1) {
  455.         vol->curDirPtr = nSect;
  456. //        (*adfEnv.notifyFct)(0,ST_ROOT);
  457.         return RC_OK;
  458.     }
  459.     else
  460.         return RC_ERROR;
  461. }
  462.  
  463.  
  464. /*
  465.  * adfParentDir
  466.  *
  467.  */
  468. SECTNUM adfParentDir(struct Volume* vol)
  469. {
  470.     struct bEntryBlock entry;
  471.  
  472.     if (vol->curDirPtr!=vol->rootBlock) {
  473.         if (adfReadEntryBlock( vol, vol->curDirPtr, &entry )!=RC_OK)
  474.             return RC_ERROR;
  475.         vol->curDirPtr = entry.parent;
  476.     }
  477.     return RC_OK;
  478. }
  479.  
  480.  
  481. /*
  482.  * adfEntBlock2Entry
  483.  *
  484.  */
  485. RETCODE adfEntBlock2Entry(struct bEntryBlock *entryBlk, struct Entry *entry)
  486. {
  487.     char buf[MAXCMMTLEN+1];
  488.     int len;
  489.  
  490.     entry->type = entryBlk->secType;
  491.     entry->parent = entryBlk->parent;
  492.  
  493.     len = min(entryBlk->nameLen, MAXNAMELEN);
  494.     strncpy(buf, entryBlk->name, len);
  495.     buf[len] = '\0';
  496.     entry->name = strdup(buf);
  497.     if (entry->name==NULL)
  498.         return RC_MALLOC;
  499. //printf("len=%d name=%s parent=%ld\n",entryBlk->nameLen, entry->name,entry->parent );
  500.     adfDays2Date( entryBlk->days, &(entry->year), &(entry->month), &(entry->days));
  501.     entry->hour = entryBlk->mins/60;
  502.     entry->mins = entryBlk->mins%60;
  503.     entry->secs = entryBlk->ticks/50;
  504.  
  505.     entry->access = -1;
  506.     entry->size = 0L;
  507.     entry->comment = NULL;
  508.     entry->real = 0L;
  509.     switch(entryBlk->secType) {
  510.     case ST_ROOT:
  511.         break;
  512.     case ST_DIR:
  513.         entry->access = entryBlk->access;
  514.         len = min(entryBlk->commLen, MAXCMMTLEN);
  515.         strncpy(buf, entryBlk->comment, len);
  516.         buf[len] = '\0';
  517.         entry->comment = strdup(buf);
  518.         if (entry->comment==NULL) {
  519.             free(entry->name);
  520.             return RC_MALLOC;
  521.         }
  522.         break;
  523.     case ST_FILE:
  524.         entry->access = entryBlk->access;
  525.         entry->size = entryBlk->byteSize;
  526.         len = min(entryBlk->commLen, MAXCMMTLEN);
  527.         strncpy(buf, entryBlk->comment, len);
  528.         buf[len] = '\0';
  529.         entry->comment = strdup(buf);
  530.         if (entry->comment==NULL) {
  531.             free(entry->name);
  532.             return RC_MALLOC;
  533.         }
  534.         break;
  535.     case ST_LFILE:
  536.     case ST_LDIR:
  537.         entry->real = entryBlk->realEntry;
  538.     case ST_LSOFT:
  539.         break;
  540.     default:
  541.         (*adfEnv.wFct)("unknown entry type");
  542.     }
  543.     
  544.     return RC_OK;
  545. }
  546.  
  547.  
  548. /*
  549.  * adfNameToEntryBlk
  550.  *
  551.  */
  552. SECTNUM adfNameToEntryBlk(struct Volume *vol, long ht[], char* name, 
  553.     struct bEntryBlock *entry, SECTNUM *nUpdSect)
  554. {
  555.     int hashVal;
  556.     char upperName[MAXNAMELEN+1];
  557.     char upperName2[MAXNAMELEN+1];
  558.     SECTNUM nSect;
  559.     int nameLen;
  560.     BOOL found;
  561.     SECTNUM updSect;
  562.     BOOL intl;
  563.  
  564.     intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
  565.     hashVal = adfGetHashValue( name, intl );
  566.     nameLen = strlen(name);
  567.     myToUpper( upperName, name, nameLen, intl );
  568.  
  569.     nSect = ht[hashVal];
  570.     if (nSect==0)
  571.         return -1;
  572.  
  573.     updSect = 0;
  574.     found = FALSE;
  575.     do {
  576.         if (adfReadEntryBlock(vol, nSect, entry)!=RC_OK)
  577.             return -1;
  578.         if (nameLen==entry->nameLen) {
  579.             myToUpper( upperName2, entry->name, nameLen, isINTL(vol->dosType) );
  580.             found = strncmp(upperName, upperName2, nameLen)==0;
  581.         }
  582.         if (!found) {
  583.             updSect = nSect;
  584.             nSect = entry->nextSameHash; 
  585.         }
  586.     }while( !found && nSect!=0 );
  587.  
  588.     if ( nSect==0 && !found )
  589.         return -1;
  590.     else {
  591.         if (nUpdSect!=NULL)
  592.             *nUpdSect = updSect;
  593.         return nSect;
  594.     }
  595. }
  596.  
  597.  
  598. /*
  599.  * Access2String
  600.  *
  601.  */
  602.     char* 
  603. adfAccess2String(long acc)
  604. {
  605.     static char ret[8+1];
  606.  
  607.     strcpy(ret,"----rwed");
  608.     if (hasD(acc)) ret[7]='-';
  609.     if (hasE(acc)) ret[6]='-';
  610.     if (hasW(acc)) ret[5]='-';
  611.     if (hasR(acc)) ret[4]='-';
  612.     if (hasA(acc)) ret[3]='a';
  613.     if (hasP(acc)) ret[2]='p';
  614.     if (hasS(acc)) ret[1]='s';
  615.     if (hasH(acc)) ret[0]='h';
  616.  
  617.     return(ret);
  618. }
  619.  
  620.  
  621. /*
  622.  * adfCreateEntry
  623.  *
  624.  */
  625. SECTNUM adfCreateEntry(struct Volume *vol, struct bEntryBlock *dir, char *name )
  626. {
  627.     BOOL intl;
  628.     struct bEntryBlock updEntry;
  629.     int len, hashValue;
  630.     RETCODE rc;
  631.     char name2[MAXNAMELEN+1], name3[MAXNAMELEN+1];
  632.     SECTNUM nSect, newSect, newSect2;
  633.     struct bRootBlock* root;
  634.  
  635. //puts("adfCreateEntry in");
  636.  
  637.     intl = isINTL(vol->dosType) || isDIRCACHE(vol->dosType);
  638.     len = strlen(name);
  639.     myToUpper(name2, name, len, intl);
  640.     hashValue = adfGetHashValue(name, intl);
  641.     nSect = dir->hashTable[ hashValue ];
  642.  
  643.     if ( nSect==0 ) {
  644.         newSect = adfGet1FreeBlock(vol);
  645.         if (newSect==-1) {
  646.            (*adfEnv.wFct)("adfCreateEntry : nSect==-1");
  647.            return -1;
  648.         }
  649.  
  650.         dir->hashTable[ hashValue ] = newSect;
  651.         if (dir->secType==ST_ROOT) {
  652.             root = (struct bRootBlock*)dir;
  653.             adfTime2AmigaTime(adfGiveCurrentTime(),
  654.                 &(root->cDays),&(root->cMins),&(root->cTicks));
  655.             rc=adfWriteRootBlock(vol, vol->rootBlock, root);
  656.         }
  657.         else {
  658.             adfTime2AmigaTime(adfGiveCurrentTime(),&(dir->days),&(dir->mins),&(dir->ticks));
  659.             rc=adfWriteDirBlock(vol, dir->headerKey, (struct bDirBlock*)dir);
  660.         }
  661. //puts("adfCreateEntry out, dir");
  662.         if (rc!=RC_OK) {
  663.             adfSetBlockFree(vol, newSect);    
  664.             return -1;
  665.         }
  666.         else
  667.             return( newSect );
  668.     }
  669.  
  670.     do {
  671.         if (adfReadEntryBlock(vol, nSect, &updEntry)!=RC_OK)
  672.             return -1;
  673.         if (updEntry.nameLen==len) {
  674.             myToUpper(name3,updEntry.name,updEntry.nameLen,intl);
  675.             if (strncmp(name3,name2,len)==0) {
  676.                 (*adfEnv.wFct)("adfCreateEntry : entry already exists");
  677.                 return -1;
  678.             }
  679.         }
  680.         nSect = updEntry.nextSameHash;
  681.     }while(nSect!=0);
  682.  
  683.     newSect2 = adfGet1FreeBlock(vol);
  684.     if (newSect2==-1) {
  685.         (*adfEnv.wFct)("adfCreateEntry : nSect==-1");
  686.         return -1;
  687.     }
  688.      
  689.     rc = RC_OK;
  690.     updEntry.nextSameHash = newSect2;
  691.     if (updEntry.secType==ST_DIR)
  692.         rc=adfWriteDirBlock(vol, updEntry.headerKey, (struct bDirBlock*)&updEntry);
  693.     else if (updEntry.secType==ST_FILE)
  694.         rc=adfWriteFileHdrBlock(vol, updEntry.headerKey, 
  695.             (struct bFileHeaderBlock*)&updEntry);
  696.     else
  697.         (*adfEnv.wFct)("adfCreateEntry : unknown entry type");
  698.  
  699. //puts("adfCreateEntry out, hash");
  700.     if (rc!=RC_OK) {
  701.         adfSetBlockFree(vol, newSect2);    
  702.         return -1;
  703.     }
  704.     else
  705.         return(newSect2);
  706. }
  707.  
  708.  
  709. /*
  710.  * myToUpper
  711.  *
  712.  */
  713.     void
  714. myToUpper( char *nstr, char *ostr, int nlen, BOOL intl )
  715. {
  716.     int i;
  717.  
  718.     if (intl)
  719.         for(i=0; i<nlen; i++)
  720.             nstr[i]=adfIntlToUpper(ostr[i]);
  721.     else
  722.         for(i=0; i<nlen; i++)
  723.             nstr[i]=toupper(ostr[i]);
  724.     nstr[nlen]='\0';
  725. }
  726.  
  727.  
  728. /*
  729.  * adfIntlToUpper
  730.  *
  731.  */
  732.     int 
  733. adfIntlToUpper(int c)
  734. {
  735. return (c>='a' && c<='z') || (c>=224 && c<=254 && c!=247) ? c - ('a'-'A') : c ;
  736. }
  737.  
  738.  
  739. /*
  740.  * adfGetHashValue
  741.  * 
  742.  */
  743.     int 
  744. adfGetHashValue(char *name, BOOL intl)
  745. {
  746.     int hash;
  747.     int i,len;
  748.  
  749.     len = hash = strlen(name);
  750.     for(i=0; i<len; i++) {
  751.         hash = hash*13;
  752.         if (intl)
  753.                 hash = hash + adfIntlToUpper(name[i]);
  754.         else
  755.                 hash = hash + toupper(name[i]);
  756.         hash = hash & 0x7ff;
  757.     }
  758.     hash = hash % HT_SIZE;
  759.  
  760.     return(hash);
  761. }
  762.  
  763.  
  764. /*
  765.  * printEntry
  766.  *
  767.  */
  768. void printEntry(struct Entry* entry)
  769. {
  770.     printf("%-30s %2d %6ld ", entry->name, entry->type, entry->sector);
  771.     printf("%2d/%02d/%04d %2d:%02d:%02d",entry->days, entry->month, entry->year,
  772.         entry->hour, entry->mins, entry->secs);
  773.     if (entry->type==ST_FILE)
  774.         printf("%8ld ",entry->size);
  775.     else
  776.         printf("         ");
  777.     if (entry->type==ST_FILE || entry->type==ST_DIR)
  778.         printf("%-s ",adfAccess2String(entry->access));
  779.     if (entry->comment!=NULL)
  780.         printf("%s ",entry->comment);
  781.     putchar('\n');
  782. }
  783.  
  784.  
  785. /*
  786.  * adfCreateDir
  787.  *
  788.  */
  789. RETCODE adfCreateDir(struct Volume* vol, SECTNUM nParent, char* name)
  790. {
  791.     SECTNUM nSect;
  792.     struct bDirBlock dir;
  793.     struct bEntryBlock parent;
  794. //    SECTNUM nCache;
  795.  
  796.     if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK)
  797.         return RC_ERROR;
  798.  
  799.     nSect = adfCreateEntry(vol, &parent, name);
  800.     if (nSect==-1) {
  801.         (*adfEnv.wFct)("adfCreateDir : no sector available");
  802.         return RC_ERROR;
  803.     }
  804.     memset(&dir, 0, sizeof(struct bDirBlock));
  805.     dir.nameLen = min(MAXNAMELEN, strlen(name));
  806.     memcpy(dir.dirName,name,dir.nameLen);
  807.     dir.headerKey = nSect;
  808.  
  809.     if (parent.secType==ST_ROOT)
  810.         dir.parent = vol->rootBlock;
  811.     else
  812.         dir.parent = parent.headerKey;
  813.     adfTime2AmigaTime(adfGiveCurrentTime(),&(dir.days),&(dir.mins),&(dir.ticks));
  814.  
  815.     if (isDIRCACHE(vol->dosType)) {
  816.         adfAddInCache(vol, &parent, (struct bEntryBlock *)&dir);
  817.         /* for adfCreateEmptyCache, will be added by adfWriteDirBlock */
  818.         dir.secType = ST_DIR;
  819.         adfCreateEmptyCache(vol, (struct bEntryBlock *)&dir, -1);
  820.     }
  821.  
  822.     /* writes the dirblock, with the possible dircache assiocated */
  823.     if (adfWriteDirBlock(vol, nSect, &dir)!=RC_OK)
  824.         return RC_ERROR;
  825.  
  826.     adfUpdateBitmap(vol);
  827.  
  828.     (*adfEnv.notifyFct)(nParent,ST_DIR);
  829.  
  830.     return RC_OK;
  831. }
  832.  
  833.  
  834. /*
  835.  * adfCreateFile
  836.  *
  837.  */
  838. RETCODE adfCreateFile(struct Volume* vol, SECTNUM nParent, char *name,
  839.     struct bFileHeaderBlock *fhdr)
  840. {
  841.     SECTNUM nSect;
  842.     struct bEntryBlock parent;
  843. //puts("adfCreateFile in");
  844.     if (adfReadEntryBlock(vol, nParent, &parent)!=RC_OK)
  845.         return RC_ERROR;
  846.  
  847.     nSect = adfCreateEntry(vol, &parent, name);
  848.     if (nSect==-1) return RC_ERROR;
  849. /*printf("new fhdr=%d\n",nSect);*/
  850.     memset(fhdr,0,512);
  851.     fhdr->nameLen = min(MAXNAMELEN, strlen(name));
  852.     memcpy(fhdr->fileName,name,fhdr->nameLen);
  853.     fhdr->headerKey = nSect;
  854.     if (parent.secType==ST_ROOT)
  855.         fhdr->parent = vol->rootBlock;
  856.     else if (parent.secType==ST_DIR)
  857.         fhdr->parent = parent.headerKey;
  858.     else
  859.         (*adfEnv.wFct)("adfCreateFile : unknown parent secType");
  860.     adfTime2AmigaTime(adfGiveCurrentTime(),
  861.         &(fhdr->days),&(fhdr->mins),&(fhdr->ticks));
  862.  
  863.     if (adfWriteFileHdrBlock(vol,nSect,fhdr)!=RC_OK)
  864.         return RC_ERROR;
  865.  
  866.     if (isDIRCACHE(vol->dosType))
  867.         adfAddInCache(vol, &parent, (struct bEntryBlock *)fhdr);
  868.  
  869.     adfUpdateBitmap(vol);
  870. //puts("adfCreateFile out");
  871.  
  872.     (*adfEnv.notifyFct)(nParent,ST_FILE);
  873.  
  874.     return RC_OK;
  875. }
  876.  
  877.  
  878. /*
  879.  * adfReadEntryBlock
  880.  *
  881.  */
  882. RETCODE adfReadEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock *ent)
  883. {
  884.     unsigned char buf[512];
  885.  
  886.     if (adfReadBlock(vol, nSect, buf)!=RC_OK)
  887.         return RC_ERROR;
  888.  
  889.     memcpy(ent, buf, 512);
  890. #ifdef LITT_ENDIAN
  891.     swapEndian((unsigned char*)ent, SWBL_ENTRY);
  892. #endif
  893. /*printf("readentry=%d\n",nSect);*/
  894.     if (ent->checkSum!=adfNormalSum((unsigned char*)buf,20,512)) {
  895.         (*adfEnv.wFct)("adfReadEntryBlock : invalid checksum");
  896.         return RC_ERROR;
  897.     }
  898.     if (ent->type!=T_HEADER) {
  899.         (*adfEnv.wFct)("adfReadEntryBlock : T_HEADER id not found");
  900.         return RC_ERROR;
  901.     }
  902.     if (ent->nameLen<0 || ent->nameLen>MAXNAMELEN || ent->commLen>MAXCMMTLEN) {
  903.         (*adfEnv.wFct)("adfReadEntryBlock : nameLen or commLen incorrect"); 
  904.         printf("nameLen=%d, commLen=%d, name=%s sector%ld\n",
  905.             ent->nameLen,ent->commLen,ent->name, ent->headerKey);
  906.     }
  907.  
  908.     return RC_OK;
  909. }
  910.  
  911.  
  912. /*
  913.  * adfWriteEntryBlock
  914.  *
  915.  */
  916. RETCODE adfWriteEntryBlock(struct Volume* vol, SECTNUM nSect, struct bEntryBlock *ent)
  917. {
  918.     unsigned char buf[512];
  919.     unsigned long newSum;
  920.    
  921.  
  922.     memcpy(buf, ent, sizeof(struct bEntryBlock));
  923.  
  924. #ifdef LITT_ENDIAN
  925.     swapEndian(buf, SWBL_ENTRY);
  926. #endif
  927.     newSum = adfNormalSum(buf,20,sizeof(struct bEntryBlock));
  928.     swLong(buf+20, newSum);
  929.  
  930.     if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
  931.         return RC_ERROR;
  932.  
  933.     return RC_OK;
  934. }
  935.  
  936.  
  937. /*
  938.  * adfWriteDirBlock
  939.  *
  940.  */
  941. RETCODE adfWriteDirBlock(struct Volume* vol, SECTNUM nSect, struct bDirBlock *dir)
  942. {
  943.     unsigned char buf[512];
  944.     unsigned long newSum;
  945.     
  946.  
  947. /*printf("wdirblk=%d\n",nSect);*/
  948.     dir->type = T_HEADER;
  949.     dir->highSeq = 0;
  950.     dir->hashTableSize = 0;
  951.     dir->secType = ST_DIR;
  952.  
  953.     memcpy(buf, dir, sizeof(struct bDirBlock));
  954. #ifdef LITT_ENDIAN
  955.     swapEndian(buf, SWBL_DIR);
  956. #endif
  957.     newSum = adfNormalSum(buf,20,sizeof(struct bDirBlock));
  958.     swLong(buf+20, newSum);
  959.  
  960.     if (adfWriteBlock(vol, nSect, buf)!=RC_OK)
  961.         return RC_ERROR;
  962.  
  963.     return RC_OK;
  964. }
  965.  
  966.  
  967.  
  968. /*###########################################################################*/
  969.